<template>
  <div :class="['component', { active: active }]">
    <div
      :style="{
        ...style
      }"
    >
      <component :is="component.id" :property="component.property" />
    </div>
    <div class="component-wrap">
      <!-- 左侧组件名 -->
      <div class="component-name" v-if="component.name">
        {{ component.name }}
      </div>
      <!-- 左侧：组件操作工具栏 -->
      <div class="component-toolbar" v-if="showToolbar && component.name && active">
        <VerticalButtonGroup type="primary">
          <el-tooltip content="上移" placement="right">
            <el-button :disabled="!canMoveUp" @click.stop="handleMoveComponent(-1)">
              <Icon icon="ep:arrow-up" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="下移" placement="right">
            <el-button :disabled="!canMoveDown" @click.stop="handleMoveComponent(1)">
              <Icon icon="ep:arrow-down" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="复制" placement="right">
            <el-button @click.stop="handleCopyComponent()">
              <Icon icon="ep:copy-document" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="删除" placement="right">
            <el-button @click.stop="handleDeleteComponent()">
              <Icon icon="ep:delete" />
            </el-button>
          </el-tooltip>
        </VerticalButtonGroup>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
  // 注册所有的组件
  import { components } from '../components/mobile/index'
  export default {
    components: { ...components }
  }
</script>
<script setup lang="ts">
  import { ComponentStyle, DiyComponent } from '../util'
  import { propTypes } from '@/utils/propTypes'
  import { object } from 'vue-types'
  import { computed } from 'vue'

  /**
   * 组件容器
   * 用于包裹组件，为组件提供 背景、外边距、内边距、边框等样式
   */
  defineOptions({ name: 'ComponentContainer' })

  type DiyComponentWithStyle = DiyComponent<any> & { property: { style?: ComponentStyle } }
  const props = defineProps({
    component: object<DiyComponentWithStyle>().isRequired,
    active: propTypes.bool.def(false),
    canMoveUp: propTypes.bool.def(false),
    canMoveDown: propTypes.bool.def(false),
    showToolbar: propTypes.bool.def(true)
  })

  /**
   * 组件样式
   */
  const style = computed(() => {
    let componentStyle = props.component.property.style
    if (!componentStyle) {
      return {}
    }
    return {
      marginTop: `${componentStyle.marginTop || 0}px`,
      marginBottom: `${componentStyle.marginBottom || 0}px`,
      marginLeft: `${componentStyle.marginLeft || 0}px`,
      marginRight: `${componentStyle.marginRight || 0}px`,
      paddingTop: `${componentStyle.paddingTop || 0}px`,
      paddingRight: `${componentStyle.paddingRight || 0}px`,
      paddingBottom: `${componentStyle.paddingBottom || 0}px`,
      paddingLeft: `${componentStyle.paddingLeft || 0}px`,
      borderTopLeftRadius: `${componentStyle.borderTopLeftRadius || 0}px`,
      borderTopRightRadius: `${componentStyle.borderTopRightRadius || 0}px`,
      borderBottomRightRadius: `${componentStyle.borderBottomRightRadius || 0}px`,
      borderBottomLeftRadius: `${componentStyle.borderBottomLeftRadius || 0}px`,
      overflow: 'hidden',
      background:
        componentStyle.bgType === 'color' ? componentStyle.bgColor : `url(${componentStyle.bgImg})`
    }
  })

  const emits = defineEmits<{
    (e: 'move', direction: number): void
    (e: 'copy'): void
    (e: 'delete'): void
  }>()
  /**
   * 移动组件
   * @param direction 移动方向
   */
  const handleMoveComponent = (direction: number) => {
    emits('move', direction)
  }
  /**
   * 复制组件
   */
  const handleCopyComponent = () => {
    emits('copy')
  }
  /**
   * 删除组件
   */
  const handleDeleteComponent = () => {
    emits('delete')
  }
</script>

<style scoped lang="scss">
  $active-border-width: 2px;
  $hover-border-width: 1px;
  $name-position: -85px;
  $toolbar-position: -55px;

  /* 组件 */
  .component {
    position: relative;
    cursor: move;

    .component-wrap {
      position: absolute;
      top: 0;
      left: -$active-border-width;
      display: block;
      width: 100%;
      height: 100%;

      /* 鼠标放到组件上时 */
      &:hover {
        border: $hover-border-width dashed var(--el-color-primary);
        box-shadow: 0 0 5px 0 rgb(24 144 255 / 30%);

        .component-name {
          top: $hover-border-width;

          /* 防止加了边框之后，位置移动 */
          left: $name-position - $hover-border-width;
        }
      }

      /* 左侧：组件名称 */
      .component-name {
        position: absolute;
        top: $active-border-width;
        left: $name-position;
        display: block;
        width: 80px;
        height: 25px;
        font-size: 12px;
        line-height: 25px;
        text-align: center;
        background: #fff;
        box-shadow:
          0 0 4px #00000014,
          0 2px 6px #0000000f,
          0 4px 8px 2px #0000000a;

        /* 右侧小三角 */
        &::after {
          position: absolute;
          top: 7.5px;
          right: -10px;
          width: 0;
          height: 0;
          border: 5px solid transparent;
          border-left-color: #fff;
          content: ' ';
        }
      }

      /* 右侧：组件操作工具栏 */
      .component-toolbar {
        position: absolute;
        top: 0;
        right: $toolbar-position;
        display: none;

        /* 左侧小三角 */
        &::before {
          position: absolute;
          top: 10px;
          left: -10px;
          width: 0;
          height: 0;
          border: 5px solid transparent;
          border-right-color: #2d8cf0;
          content: ' ';
        }
      }
    }

    /* 组件选中时 */
    &.active {
      margin-bottom: 4px;

      .component-wrap {
        margin-bottom: $active-border-width + $active-border-width;
        border: $active-border-width solid var(--el-color-primary) !important;
        box-shadow: 0 0 10px 0 rgb(24 144 255 / 30%);

        .component-name {
          top: 0 !important;

          /* 防止加了边框之后，位置移动 */
          left: $name-position - $active-border-width !important;
          color: #fff;
          background: var(--el-color-primary);

          &::after {
            border-left-color: var(--el-color-primary);
          }
        }

        .component-toolbar {
          display: block;
        }
      }
    }
  }
</style>
